import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

typedef OnChildSizeChanged = void Function(Size size);

class WidgetSizeRenderObject extends RenderProxyBox {
  OnChildSizeChanged? onWidgetSizeChange;
  Size currentSize = Size.zero;

  WidgetSizeRenderObject(this.onWidgetSizeChange);

  @override
  void performLayout() {
    super.performLayout();
    try {
      Size? size = child?.size;
      if (size != null && currentSize != size) {
        currentSize = size;
        onWidgetSizeChange?.call(size);
      }
    } catch (e) {
      if (hasSize) onWidgetSizeChange?.call(size);
    }
  }
}

class DynamicSizeWrapper extends SingleChildRenderObjectWidget {
  final OnChildSizeChanged? onChildSizeChanged;
  const DynamicSizeWrapper({
    Key? key,
    this.onChildSizeChanged,
    required Widget child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return WidgetSizeRenderObject(onChildSizeChanged);
  }

  @override
  void updateRenderObject(
      BuildContext context, WidgetSizeRenderObject renderObject) {
    super.updateRenderObject(context, renderObject);
    // 保证renderObject的onWidgetSizeChange始终是最新的
    renderObject.onWidgetSizeChange = onChildSizeChanged;
  }
}

class ChildSizeWrap extends SingleChildRenderObjectWidget {
  final void Function(Size)? onChildSizeChanged;

  const ChildSizeWrap({
    Key? key,
    Widget? child,
    this.onChildSizeChanged,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderChildSize().._associatedWidget = this;
  }

  @override
  void updateRenderObject(BuildContext context, RenderChildSize renderObject) {
    renderObject._associatedWidget = this;
  }
}

class RenderChildSize extends RenderBox
    with RenderObjectWithChildMixin<RenderBox> {
  var _lastSize = Size.zero;
  var _associatedWidget = const ChildSizeWrap();

  @override
  void performLayout() {
    final child = this.child;
    if (child != null) {
      try {
        child.layout(constraints, parentUsesSize: true);
        size = child.size;
      } catch (e) {
        // 处理异常情况下的size设置
        size = constraints.smallest;
      }
    } else {
      size = constraints.smallest;
    }

    // 检查大小是否实际变化
    if (_lastSize != size) {
      _lastSize = size;
      _associatedWidget.onChildSizeChanged?.call(_lastSize);
    }
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final child = this.child;
    if (child != null) {
      context.paintChild(child, offset);
    }
  }

  @override
  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
    return child?.hitTest(result, position: position) == true;
  }
}
